'use strict';

/**
 * 巨龙jHD23设备专用
 * 提供给julong_jHD23设备相关接口
 * 抓拍：记录保存，学生打卡
 * 心跳
 * 注册：设备发起注册进后台系统
 */
const fs = require('fs');
const router = require('koa-router')();
const mongoose = require('mongoose');
const ipcModel = require('../models/ipc.model');
const recordStrangerModel = require('../models/record_stranger.model');
const recordStudentModel = require('../models/record_student.model');
const classAttendanceModel = require('../models/class_attendance.model');
const userModel = require('../models/user.model');
const httpUtil = require('../utils/http');
const Cons = require('./constants');
const globalConfig = require('../../config/global_config');

// 人脸识别参数
const generateParams = (Data) => {
    return {
        operate_cmd:3 ,//#1 增加，2 删除 ，3.获取人脸识别结果， 4.获取该图片中人脸特征向量（默认一个最大人脸） 5清空 6同步
        group_id:"-1",// #默认为-1，为待识别人脸所在的库id
        feature_id:-1, //默认为-1， 只有在增加、删除操作有值,对数据库操作时需要确定修改的标识，(该值对应是某个人的id还是某一个人脸特征id需要考虑，并且单独个别修改还是批量修改该如何操作)
        DeviceId:Data.DeviceInfo.DeviceId, //设备序列号
        SendTime:Data.CaptureInfo.SendTime, //发送时间
        CaptureTime:Data.CaptureInfo.CaptureTime, //抓拍时间
        CaptureCount:Data.CaptureInfo.CaptureCount, //抓拍图片计数
        FacePicture:Data.CaptureInfo.FacePicture, //人脸图片数据(base64编码格式)
        BackgroundPicture:Data.CaptureInfo.BackgroundPicture, //#照片背景图片(base64编码格式)
        FaceId:Data.FaceInfo.FaceId, //人脸ID
        FaceQuality:Data.FaceInfo.FaceQuality, // 人脸质量分数
        FacePosition:Data.FaceInfo.FacePosition, // 人脸坐标
        Liveness:Data.CompareInfo.Liveness, // 人脸活体检测.0：非活体 , 1： 活体
    }
}
// 打卡操作
const checkInAttendance = async (studentId,studentName='',studentNum='',deviceId) => {
    try{
        const currentTime = +new Date()
        const currentZeroTime = new Date().setHours(0,0,0,0)
        // 查看匹配考勤表
        const allClassAttendance = await classAttendanceModel.find({
            attendance_start_date:currentZeroTime,
            device_collection:{
                $elemMatch:{
                    device_id:deviceId
                }
            },
        })
        if(allClassAttendance&&allClassAttendance.length){
            for(let cItem of allClassAttendance){
                // 校验是否合理时间内，上课下课前后10分钟
                const startTime = cItem.class_start_time
                const endTime = cItem.class_end_time
                if(!startTime||!endTime){
                    continue
                }
                const startTimeStamp = startTime - 1000*60*10
                const endTimeStamp = endTime + 1000*60*10
                if(currentTime>startTimeStamp && currentTime<endTimeStamp){
                    const devices = cItem.device_collection||[]
                    const ids = devices.map(item=>item.device_id)
                    if(ids.includes(deviceId)){
                        const student_collection = cItem.student_collection;
                        const student = student_collection.find(item=>item.student_id==studentId)
                        if(student){
                            // 学生考勤
                            student.attendance_start_time ? (student.attendance_end_time = currentTime) : (student.attendance_start_time = currentTime)
                        }
                        // if(student){
                        //     if(student.is_invalid){
                        //         // 蹭课统计，长时间逗留
                        //         student.is_invalid++
                        //         student.attendance_end_time = currentTime;
                        //         student.student_name = studentName
                        //         student.student_id = studentId
                        //     }else{
                        //         // 学生考勤
                        //         student.attendance_start_time ? (student.attendance_end_time = currentTime) : (student.attendance_start_time = currentTime)
                        //     }
                        // }else if(currentTime>startTimeStamp+1000*60*10 && currentTime<endTimeStamp-1000*60*10){
                        //     // 新增蹭课学生
                        //     student_collection.push({
                        //         student_id:studentId,
                        //         student_name: studentName,
                        //         student_num: studentNum,
                        //         attendance_start_time:currentTime,
                        //         attendance_end_time:'',
                        //         is_invalid:1
                        //     })
                        // }
                        await classAttendanceModel.updateOne({_id:cItem._id},{
                            $set: {
                                student_collection:student_collection
                            }
                        })
                        return true
                    }
                } 
            }
        }
    }catch(err){
        console.log(err)
    }
}


// 抓拍信息
router.all('/captureinfo', async function(ctx,next){
    // console.log(111)
    const params = ctx.request.body
    if(!params){
        return ctx.body = {
            code:2,
            msg:'无抓拍信息'
        }
    }
    try{
        const DeviceInfo = params && params.Data && params.Data.DeviceInfo
        const CaptureInfo = params && params.Data && params.Data.CaptureInfo
        const CompareInfo = params && params.Data && params.Data.CompareInfo
        const PersonInfo = CompareInfo && CompareInfo.PersonInfo

        const currentTime = +new Date()
        const currentZeroTime = new Date().setHours(0,0,0,0)

        const ipc = await ipcModel.findOne({device_uuid:DeviceInfo.DeviceUUID})
        if(!ipc) {
                return  ctx.body = {
                code:2,
                msg:'设备不存在'
            } 
        }
        
        // 保存图片
        if(!fs.existsSync(globalConfig.res.julong_record_dir)){
            fs.mkdirSync(globalConfig.res.julong_record_dir)
        }
        const newBuffer = Buffer.from(CaptureInfo.FacePicture,'base64')
        // 图片名规则：时间戳_设备id_record
        const imgName = `${currentTime}_${DeviceInfo.DeviceId}_record.jpg`
        const imgPath = `${globalConfig.res.julong_record_dir}${imgName}`
        fs.writeFileSync(imgPath,newBuffer)

        if(ipc.device_type===2){
            // 后台识别
            const req = generateParams(params.Data)
            const res = await httpUtil.postWithTimeout(`${globalConfig.faceRecognitionServer}/facerec-ipc`,req)
            let student_mark = false;
            if(res.code == 200 && res.result == '200'){
                // 识别成功
                const feature_id = res.data && res.data.feature_id && res.data.feature_id[0]
                if(feature_id){
                    const matchStudent = await userModel.findOne({feature_id,u_tp:Cons.USER_TYPE_STUDENT})
                    if(matchStudent){
                        // 匹配到学生
                        student_mark = true
                        const personParams = {
                            c_time:Math.floor(currentTime/1000),
                            // c_photo:CaptureInfo.FacePicture,
                            c_photo_name:imgName,
                            d_id:DeviceInfo.DeviceId,
                            d_uuid:DeviceInfo.DeviceUUID,
                            d_name:ipc?ipc.d_nm:'Julong_jHD23',
                            s_type:2,
                            s_similarity: '',
                            s_id: matchStudent.s_id,
                            s_name: matchStudent.u_nm,
                            s_sex: matchStudent.u_sx,
                            s_num: matchStudent.s_num,
                            s_school: matchStudent.s_school,
                            s_class: matchStudent.s_class,
                            s_phone: matchStudent.u_pn,
                            s_email: matchStudent.s_email,
                            s_address: matchStudent.s_address,

                            // 设备所在教室信息
                            group_name:ipc.group_name,//集团名称
                            campus_name:ipc.campus_name,//校区名称
                            class_name:ipc.class_name,//班级名称
                            classroom_id:ipc.classroom_id,//教室id
                            classroom_name:ipc.classroom_name,//教室名称
                            classroom_num:ipc.classroom_num,//教室编号
                        }
                        await recordStudentModel.create(personParams)

                        // 打卡操作

                        const checkRes = await checkInAttendance(matchStudent._id,matchStudent.u_nm,matchStudent.s_num,DeviceInfo.DeviceId)

                        if(checkRes) {
                            return ctx.body = {
                                code:0,
                                msg:'后台识别：打卡成功'
                            }
                        }else{
                            return ctx.body = {
                                code:2,
                                msg:'后台识别：不在课表中，打卡失败'
                            }
                        }
                    }
                }
            }
            if(!student_mark){
                // 其他暂时视为陌生人
                const strangerParams = {
                    _id:new mongoose.Types.ObjectId(),
                    r_at:new Date(),
                    // r_cp:CaptureInfo.FacePicture,
                    // b_qp:CaptureInfo.FacePicture,
                    c_photo_name:imgName,
                    d_id:DeviceInfo.DeviceId,
                    d_uuid:DeviceInfo.DeviceUUID,

                    // 设备所在教室信息
                    group_name:ipc.group_name,//集团名称
                    campus_name:ipc.campus_name,//校区名称
                    class_name:ipc.class_name,//班级名称
                    classroom_id:ipc.classroom_id,//教室id
                    classroom_name:ipc.classroom_name,//教室名称
                    classroom_num:ipc.classroom_num,//教室编号
                }
                await recordStrangerModel.create(strangerParams)
                return ctx.body = {
                    code:0,
                    msg:'抓拍提示：陌生人'
                }
            }
            return
        }
        
            
        if(PersonInfo && PersonInfo.PersonId && CompareInfo.PersonType===2 ){
            // 匹配到学生
            const personParams = {
                c_time:Math.floor(currentTime/1000),
                // c_photo:CaptureInfo.FacePicture,
                c_photo_name:imgName,
                d_id:DeviceInfo.DeviceId,
                d_uuid:DeviceInfo.DeviceUUID,
                d_name:ipc?ipc.d_nm:'Julong_jHD23',
                s_type:CompareInfo.PersonType,
                s_similarity: CompareInfo.Similarity,
                s_id: PersonInfo.PersonId,
                s_name: PersonInfo.PersonName,
                s_sex: PersonInfo.Sex,
                s_num: PersonInfo.PersonExtension.PersonCode1,
                s_school: PersonInfo.PersonExtension.PersonCode2,
                s_class: PersonInfo.PersonExtension.PersonCode3,
                s_phone: PersonInfo.Phone,
                s_email: PersonInfo.PersonExtension.PersonData1,
                s_address: PersonInfo.Address,

                // 设备所在教室信息
                group_name:ipc.group_name,//集团名称
                campus_name:ipc.campus_name,//校区名称
                class_name:ipc.class_name,//班级名称
                classroom_id:ipc.classroom_id,//教室id
                classroom_name:ipc.classroom_name,//教室名称
                classroom_num:ipc.classroom_num,//教室编号
            }
            await recordStudentModel.create(personParams)
            /* 
                打卡操作
            */
           const checkRes = await checkInAttendance(PersonInfo.PersonId,PersonInfo.PersonName,PersonInfo.PersonExtension.PersonCode1,DeviceInfo.DeviceId)
            if(checkRes) {
                return ctx.body = {
                    code:0,
                    msg:'前端设备识别：打卡成功'
                }
            }else{
                return ctx.body = {
                    code:2,
                    msg:'前端设备识别：不在课表中，打卡失败'
                }
            }
        }else{
            // 其他暂时视为陌生人
            const strangerParams = {
                _id:new mongoose.Types.ObjectId(),
                r_at:new Date(),
                // r_cp:CaptureInfo.FacePicture,
                // b_qp:CaptureInfo.FacePicture,
                c_photo_name:imgName,
                d_id:DeviceInfo.DeviceId,
                d_uuid:DeviceInfo.DeviceUUID,

                // 设备所在教室信息
                group_name:ipc.group_name,//集团名称
                campus_name:ipc.campus_name,//校区名称
                class_name:ipc.class_name,//班级名称
                classroom_id:ipc.classroom_id,//教室id
                classroom_name:ipc.classroom_name,//教室名称
                classroom_num:ipc.classroom_num,//教室编号
            }
            await recordStrangerModel.create(strangerParams)
            return ctx.body = {
                code:0,
                msg:'抓拍提示：陌生人'
            }
        }
    }catch(err){
        console.log(err)
        return ctx.body = {
            code:2,
            msg:err
        }
    }
})

// 心跳
router.all('/keepalive', async function(ctx,next){
    // console.log(2)
    const params = ctx.request.body
    const data = params.Data
    const deviceInfo = data && data.DeviceInfo || {}
    const updateParams = {
        device_uuid: deviceInfo.DeviceUUID,
        device_mac: deviceInfo.DeviceMac,
        device_ip:deviceInfo.DeviceIP,
        channel_num:deviceInfo.ChannelNo,
        web_version:deviceInfo.WebVersion,
        core_version:deviceInfo.CoreVersion,
        version_date:deviceInfo.VersionDate,
        http_version:data.HTTPVersion,
        http_date:data.HTTPDate,
        register_session:params.Session,
        device_status:0
    }
    await ipcModel.findOneAndUpdate({_id:deviceInfo.DeviceId,d_tp:Cons.IPC_TYPE_jHD23 },updateParams)
    ctx.body = {
        code:1,
        msg:'心跳'
    }
})

// 注册
router.all('/register', async function(ctx,next){
    // console.log(3)
    const params = ctx.request.body
    const data = params.Data 
    const deviceInfo = data.DeviceInfo
    let resData = {
        Name:'registerResponse',
        Code:0
    }
    try{
        const device = await ipcModel.findOne({_id:deviceInfo.DeviceId,d_tp: Cons.IPC_TYPE_jHD23})
        if(device){
            const updateParams = {
                device_uuid: deviceInfo.DeviceUUID,
                device_mac: deviceInfo.DeviceMac,
                device_ip:deviceInfo.DeviceIP,
                channel_num:deviceInfo.ChannelNum,
                web_version:deviceInfo.WebVersion,
                core_version:deviceInfo.CoreVersion,
                version_date:deviceInfo.VersionDate,
                http_version:data.HTTPVersion,
                http_date:data.HTTPDate,
                device_status:0,
                alarm_switch: '',
                black_alarm_switch: '',
                white_alarm_switch: '',
                io_switch: '',
                io_type: '',
                alarm_duration: '',
                io_status_type: '',
                recognition_mode: '',
                similarity_set: '',
                alarm_start_time: '',
                alarm_end_time: '',
                subnet_mask: '',
                gateway: '',
                preferred_dns: '',
                standby_dns: ''
            }
            if(!device.register_session){
                const timeStamp = Math.floor((+new Date())/1000)
                updateParams.register_session = deviceInfo.DeviceUUID + '_' + timeStamp
                const updateDevice = await ipcModel.updateOne({_id:deviceInfo.DeviceId,d_tp: Cons.IPC_TYPE_jHD23},updateParams)
                if(updateDevice){
                    const r_session = updateParams.register_session;
                    const timeStamp = r_session.split('_')[1]
                    resData.Data = {
                        Session: r_session,
                        ServerVersion:device.http_version
                    }
                    resData.Code = 1
                    resData.TimeStamp = timeStamp
                    resData.Message = '设备注册成功'
                    return ctx.body = resData
                }
            }else{
                await ipcModel.findOneAndUpdate({_id:deviceInfo.DeviceId,d_tp: Cons.IPC_TYPE_jHD23},updateParams)
                const r_session = device.register_session;
                const timeStamp = r_session.split('_')[1]
                resData.Data = {
                    Session: r_session,
                    ServerVersion:device.http_version
                }
                resData.Code = 1
                resData.TimeStamp = timeStamp
                resData.Message = '状态已更新'
                return ctx.body = resData 
            }
        }else{
            resData.Message = '设备需要先添加才能注册'
            return ctx.body = resData
        }
    }catch(err){
        console.log(err)
        ctx.error(Code.REQUEST_ERROR('注册失败'))
    }
})

module.exports = router;